import socket
import _thread
from util.message import Message
from util.log import Log
from util.user import User

# Settings
ip = '127.0.0.1'
port = 8000

# Listener
def listener(c, ip, port, uname):
    while True:
        try:
            recv = c.recv(1024)
            msg = Message(recv)
            # Message
            if msg.type == 1:
                recv = c.recv(int(msg.data))
                msg = Message(recv)
                for i in c_list:
                    if i['addr'] != '%s:%s'%(ip, port):
                        log.msg(msg.fr, msg.data)
                        j = Message.broadcast(msg.fr, msg.data)
                        i['client'].send(Message.len(len(j)).encode('utf-8'))
                        i['client'].send(j.encode('utf-8'))
            # Login
            elif msg.type == 4:
                if msg.pwd == 'check':
                    flag = user.check(msg.user, 'check')
                    c.send(Message.login_result(flag).encode('utf-8'))
                else:
                    flag = user.login(msg.user, msg.pwd)
                    c.send(Message.login_result(flag).encode('utf-8'))
                    # Record User
                    if flag == True:
                        uname = msg.user
                        log.sys('%s@%s:%s logined.'%(uname, ip, port))
                        j = Message.notice('User %s joined.'%uname)
                        for i in c_list:
                            i['client'].send(Message.len(len(j)).encode('utf-8'))
                            i['client'].send(j.encode('utf-8'))
                        c_list.append({'addr':'%s:%s'%(ip, port), 'client':c, 'name':uname})
                    else:
                        log.sys('%s:%s login failed.'%(ip, port))
            # Register
            elif msg.type == 6:
                flag = user.register(msg.user, msg.pwd)
                c.send(Message.login_result(flag).encode('utf-8'))
                # Record User
                if flag == True:
                    uname = msg.user
                    log.sys('%s@%s:%s registered and logined.'%(uname, ip, port))
                    j = Message.notice('User %s joined.'%uname)
                    for i in c_list:
                        i['client'].send(Message.len(len(j)).encode('utf-8'))
                        i['client'].send(j.encode('utf-8'))
                    c_list.append({'addr':'%s:%s'%(ip, port), 'client':c, 'name':uname})
        except ConnectionResetError as e:
            log.sys('%s@%s:%s logged out and disconnected.'%(uname, ip, port))
            if uname != 'unknown':
                c_list.remove({'addr':'%s:%s'%(ip, port), 'client':c, 'name':uname})
                for i in c_list:
                    j = Message.notice('User %s exited.'%uname)
                    for i in c_list:
                        i['client'].send(Message.len(len(j)).encode('utf-8'))
                        i['client'].send(j.encode('utf-8'))
            break

# Send Notice
def notice(a, b):
    while True:
        msg = input()
        j = Message.notice(msg)
        if len(j) > 50000:
            print('Content is too long to send.')
            continue
        else:
            for i in c_list:
                i['client'].send(Message.len(len(j)).encode('utf-8'))
                i['client'].send(j.encode('utf-8'))

# Open Server
server = socket.socket()
server.bind((ip, port))
server.listen()

# Initial
c_list=[]
log = Log()
user = User()
log.sys('Server successfully started, listening for client.')
_thread.start_new_thread(notice, (None, None))

# Main
while True:
    c, addr = server.accept()
    log.sys('%s:%s connected.'%(addr[0], addr[1]))
    _thread.start_new_thread(listener, (c, addr[0], addr[1], 'unknown'))